﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// brief: HTTP下载相关的类
#pragma once

#include "GmepComponentUtils.h"
#include "GbmpDefines.h"

namespace gnuf
{
    class GnufProgressBar;
}

namespace gmep
{
    class IGmepCategoryInfo;
    class IGmepDisciplineInfo;
}

namespace Json
{
    class Value;
}
class QJsonArray;
class QJsonObject;
struct GmepComponent;
struct ComponentInfos;
struct GmepComponentPlaceHolderInfo;
struct ChangedComponentIdSet;

class GMEP_COMPONENT_UTILS_EXPORT ComponentHttpUtils
{
public:
    typedef typename std::map<std::wstring, const gmep::IGmepCategoryInfo*> mapCategoryInfoType;
    typedef typename std::map<std::wstring, std::vector<GmepComponent>> mapGmepComponentsType;

    /// \brief 初始化种类列表
    static bool InitCategoryList();

    /// \brief 初始化账号ID和TokenID
    static void InitAccoutAndToken();

    /// \brief 同步构件信息到sqlite数据库
    /// \param projectId - 项目ID，为了拼接缓存目录
    /// \param bDownloadAll - 下载所有构件
    /// \param succCompIdMap, 返回从云端 下载增删改列表的id version
    /// \param bNeedCopyLocalFiles - 是否从本地拷贝构件，测试使用，正常使用，不能设置为false
    /// \param downloadToTemp3DFolder merge 时需要临时下载gac png到Temp文件夹， 后续处理完重名检查后，覆盖回来
    /// \param onlySyncArchitectureComponents 仅同步建筑卫浴构件，不更新时间戳
    /// \notes 业务需求，返回多种数据，根据数据提示不同的信息
    /// 返回值 res 是真正下载、更新的数量（不包含同步的删除的，不包含从本地拷贝v1版本的构件个数）； -1 为失败
    /// 返回值 succCompIdMap是 时间差内增删改的构件
    static int SyncComponentsToDb(
        const std::wstring& projectId,
        bool &bDownloadAll,
        std::map<std::wstring, int>& succCompIdMap,
        std::vector<int>& changeCountVec,
        bool bNeedCopyLocalFiles = true,
        bool downloadToTemp3DFolder = false,
        bool onlySyncArchitectureComponents = false);

    /// 调用构件库接口 获取公共库已发布的二维图例的所有id 和 信息
    static bool GetPublicPlaceHolderInfoList(const std::wstring& strProduct2DFolder, const std::wstring& strEnterpriseProduct2DFolder, std::map<std::wstring, GmepComponentPlaceHolderInfo>& placeHolderIdInfoMap);
    /// 从网络下载
    static bool DownloadPlaceHolders(const std::wstring& enterpriseId, const std::wstring&  projectId, std::map<std::wstring, GmepComponentPlaceHolderInfo>& toSyncPlaceHolderIdInfoMap);
     /// \brief 若不存在，同步指定的公共库2D构件信息到sqlite数据库 和文件夹， 从网络下载
    static bool SyncSpecifiedPlaceHoldersToDb(const std::wstring &projectId, const std::wstring &enterpriseId, std::map<std::wstring, GmepComponentPlaceHolderInfo>& toSyncPlaceHolderIdInfoMap,
        std::map<std::wstring, std::wstring>& existPlaceHoldersIdNameMap);

    static bool SyncSpecifiedComponentsToDb(const std::wstring &projectId, const std::wstring& enterpriseId, std::map<std::wstring, ComponentInfos>& projectCompV1Map,
        std::map<std::wstring, int>& projectCompIdVerNonV1Map, bool downloadToTemp3DFolder = false);

    /// \brief 将构件信息写入数据，并显示进度条
    /// \param dbFilePath - 数据库存放地址；建议数据库内部管理，外部不需要知道
    /// \param deletedComponentIdList - 需要更新的构件信息，先删除再统一重写
    /// \param pBnufProgressBar - 进度条显示
    /// \param retCompList - 构件详细数据写入数据库
    /// \param needDownloadAll - 是否需要下载全部
    /// \return 此次更新的总数（大于0）；
    static int WriteComponentsToSql(const std::wstring dbFilePath, std::map<std::wstring, int> deletedComponentIdList,
        std::map<std::wstring, std::vector<GmepComponent>> &retCompList,
        bool needDownloadAll);

    /// \brief 更新时间到time.txt中
    /// \param projectFolder - time.txt的完整目录
    /// \param timeTxtPath - 目前加上time.txt
    /// \param bUpdateTime - 是否更新时间
    /// \param currentTime - 最新时间
    static void UpdateCurTime(const std::wstring &projectFolder, const std::wstring &timeTxtPath, const LONGLONG &currentTime, bool bUpdateTime = true);

    /// \brief 增量获取增删改的构件id
    /// \param projectId - 项目ID
    /// \param lastQueryTime - 最近的查询时间
    /// \param retCurrentTime - 当前时间
    /// \param updateComponentIdList - 需要更新的构件列表（http获取）
    /// \param deletedComponentIdList -  需要更新的构件列表
    /// \param localComponentIdList -  需要更新的构件列表（本地数据库拷贝）
    /// \param onlySyncArchitectureComponents -  仅同步建筑卫浴构件
    static bool GetChangedProjectComponentIdList(
        const std::wstring& projectId,
        LONGLONG lastQueryTime,
        LONGLONG& retCurrentTime,
        std::map<std::wstring, int>& updateComponentIdList,
        std::map<std::wstring, int>& deletedComponentIdList,
        std::map<std::wstring, ComponentInfos>& localComponentIdList,
        bool onlySyncArchitectureComponents = false);

    static bool GetChangedSanitaryComponentIdList(const std::wstring& projectId, ChangedComponentIdSet& changedComponentIdSet);

    static bool GetChangedComponentIdList(const std::wstring& projectId, ChangedComponentIdSet& changedComponentIdSet);

    ///// \brief 根据publicComponentId，从本地数据库中获取数据
    ///// \param pBnufProgressBar - 进度条
    ///// \param projectId - 项目ID
    ///// \param localComponentIdList - 需要更新的构件列表（本地数据库拷贝）
    ///// \param retCompList - 数据存放处
    //static bool GetProjectComponentListFromLocal(gnuf::GnufProgressBar *pBnufProgressBar, std::wstring projectId,
    //    std::map<std::wstring, ComponentInfos>& localComponentIdList, std::map<std::wstring, std::vector<GmepComponent>>& retCompList);

    /// \brief 从本地下载 构件详情
    /// \param localComponentIdList - 需要更新的构件列表（本地数据库拷贝）
    /// \param retCompList - 数据存放处
    /// \notes 本地数据库没有的构件详情，则不加入retCompList
    /// \notes localComponentIdList中保留的项，拷贝到updateComponentIdList，走下载流程
    /// \notes 如果加入了retCompList，则从localComponentIdList中删除
    static bool GetProjectComponentDetailFromLocal(const std::wstring& projectId, std::map<std::wstring, ComponentInfos>& localComponentIdList,
        std::map<std::wstring, std::vector<GmepComponent>>& retCompList);

    /// \brief 根据构件列表，从HTTP上下载构件的数据，并解析，存入retCompList中
    /// \param pBnufProgressBar - 进度条
    /// \param projectId - 项目ID
    /// \param updateComponentIdList - 需要更新的构件列表
    /// \param retCompList - 数据存放处
    static bool GetProjectComponentListFromHttp(gnuf::GnufProgressBar *pBnufProgressBar, const int& nTotalComponentCount
        , int& nCurComponentCount, const std::wstring& projectId, const std::wstring& enterpriseId, std::map<std::wstring, int> ComponentIdList
        , const std::wstring& project3DProductFolder, std::map<std::wstring, std::vector<GmepComponent>>& retCompList);

   // static void CopyOrDownloadComponentFiles(std::vector<GmepComponent>& compList, const std::wstring &projectId, const std::wstring& enterpriseId);

   /* /// \brief 根据单个构件ID，从HTTP上下载构件的数据，并解析，存入retComponent
    /// \param pBnufProgressBar - 进度条
    /// \param projectId - 项目ID
    /// \param updateComponentIdList - 需要更新的构件列表
    static bool GetProjectComponentDetailFromHttp(const std::wstring& projectId, std::wstring componentIdStr, int version,
        const std::wstring& projectProductFolder,
        const std::wstring& project3DProductFolder, const std::wstring& project2DProductFolder, GmepComponent& retComponent);*/

    /// \brief 传入componentIdStr和version，通过HTTP请求数据
    /// \param wstrURL - 需要GET的URL
    /// \param strComponentDetail - 下载下来的数据字符串
    //static bool GetComponentDetailFromHttp(web::http::client::http_client client, const std::wstring &wstrURL, const std::wstring &wstrVersion, std::string& strComponentDetail);

    /// \brief 获取种类信息数据
    /// \param category - 信息数据，递归实现
    /// \return key - 一级分类码； IGmepCategoryInfo - 信息；包含目录名等等
    static std::map<std::wstring, const gmep::IGmepCategoryInfo*> getEndCategoryList(const gmep::IGmepCategoryInfo* category);

    static std::map<std::wstring, const gmep::IGmepCategoryInfo*>& GetGmepCategoryList();


    /// \brief 获取时间段内 增量增删改的构件id 和version
    /// \return updateComponentIdList 该段时间内新增或更新的构件id 和version； deletedComponentIdList该段时间内删除的构件id version
    static bool GetProjectChangedIdListDuringTheTime(const std::wstring& projectId, std::map<std::wstring, int>&addedComponentIdList, std::map<std::wstring, int>& updateComponentIdList,
        std::map<std::wstring, int>& deletedComponentIdList);

    static bool  DownLoadProjectComponentFamilyFile(const std::wstring &projectId, const std::wstring &componentId, const std::wstring &version, const std::wstring &strPath);

    //static bool  BathDownLoadProjectComponentFamilyFile(const std::wstring &projectId, const std::vector<HttpComponentInfo>& listComponentInfo, const std::wstring &strPath);

private:


   // static bool DownLoadComponent3DFamilyFiles(const std::wstring& projectId, const GmepComponent& comp);

    /// \brief 从本地产品文件夹拷贝文件到APPGmep中，如果文件夹不存在，会创建
    /// \param componentInfo - 构件信息
    /// \return false - 目录不存在，或本地缺少该文件
    /// \return true - 拷贝完成
   // static bool Copy3DFileFromProductFolder(const GmepComponent &componentInfo);

    static bool Copy2DFileFromProductFolder(const GmepComponentPlaceHolderInfo &placeHolderInfo);

    static bool Download3DfilesFromHttpParallel(const std::wstring& projectId, const std::wstring& enterpriseId,const std::map<std::wstring, std::vector<GmepComponent>>& retCompList);
    
    /// \brief 下载图例构件
    ///
    /// \param projectId 项目id
    /// \param enterpriseId 企业库id
    /// \param placeholderDownloadInfo 图例的下载信息
    /// \return 
    static bool Download2DFilesFromHttpParallel(
        const std::wstring & projectId,
        const std::wstring & enterpriseId,
        std::vector<std::tuple<std::wstring, std::wstring, GmepComponentPlaceHolderInfo>> placeholderDownloadInfo);
    /// \brief 从json值对象中获取构件的详细信息
    /// \param retComponent - 构件信息
    /// \return false - 读取构件详细信息失败
    /// \return true - 读取构件详细信息成功
    static bool ComponentHttpUtils::GetProjectComponentDetailFromJson(
        const std::wstring& projectId, 
        const Json::Value& compValue,
        const std::wstring& projectProductFolder,
        const std::wstring& project3DProductFolder, 
        const std::wstring& project2DProductFolder,
        GmepComponent& retComponent);

    /// \brief 从json值对象中更新构件的详细信息
    /// \param component - 构件信息
    /// \return false - 更新构件详细信息失败
    /// \return true - 更新构件详细信息成功
    static bool UpdateComponentPlaceHolderInfo(
        std::vector<GmepComponent> &categoryComponents,
        const std::wstring componentId,
        const int version,
        const Json::Value& placeholderJsValue,
        GmepComponent&component,
        bool isPrivateEnv = false);

    static bool GetNeedDownloadPlaceholderInfo(
        std::vector<GmepComponent> &categoryComponents,
        std::vector<std::tuple<std::wstring, std::wstring, GmepComponentPlaceHolderInfo>>& downloadInfo);

    /* static bool GetComponentPlaceholderInfo(
         const std::wstring& projectId,
         const std::string & componentsInfo,
         const std::map<std::wstring, std::wstring>& componentIdCategoryCodeMap,
         std::map<std::wstring, std::vector<GmepComponent>>& retCompList);*/
private:
    static std::wstring m_strAccountId;
    static std::wstring m_strTokenId;
    static std::map<std::wstring, gcmp::OwnerPtr<gmep::IGmepDisciplineInfo>> m_retDisciplineList;
    static std::map<std::wstring, const gmep::IGmepCategoryInfo*> m_gmepCategoryList;   // 用的地方比较多，所以单独拿出来
};
